//! # 配置构建器工具
//!
//! 提供通用的配置构建器模式和工具，避免在各个模块中重复实现相同的构建器逻辑。

use std::time::Duration;
use std::collections::HashMap;
use serde::{Deserialize, Serialize};

/// 配置构建器特征
pub trait ConfigBuilder<T> {
    /// 构建配置对象
    fn build(self) -> Result<T, String>;
    
    /// 验证配置的有效性
    fn validate(&self) -> Result<(), String>;
}

/// 连接池配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ConnectionPoolConfig {
    /// 最大连接数
    pub max_connections: u32,
    /// 最小连接数
    pub min_connections: u32,
    /// 连接超时时间
    pub connection_timeout: Duration,
    /// 空闲超时时间
    pub idle_timeout: Duration,
    /// 获取连接超时时间
    pub acquire_timeout: Duration,
    /// 连接验证间隔
    pub validation_interval: Duration,
    /// 是否启用连接验证
    pub validation_enabled: bool,
}

impl Default for ConnectionPoolConfig {
    fn default() -> Self {
        Self {
            max_connections: 100,
            min_connections: 10,
            connection_timeout: Duration::from_secs(30),
            idle_timeout: Duration::from_secs(300),
            acquire_timeout: Duration::from_secs(10),
            validation_interval: Duration::from_secs(30),
            validation_enabled: true,
        }
    }
}

impl ConnectionPoolConfig {
    /// 创建配置构建器
    pub fn builder() -> ConnectionPoolConfigBuilder {
        ConnectionPoolConfigBuilder::new()
    }

    /// 验证配置的有效性
    pub fn validate(&self) -> Result<(), String> {
        if self.max_connections == 0 {
            return Err("最大连接数必须大于0".to_string());
        }
        
        if self.min_connections > self.max_connections {
            return Err("最小连接数不能大于最大连接数".to_string());
        }
        
        if self.connection_timeout.is_zero() {
            return Err("连接超时时间必须大于0".to_string());
        }
        
        if self.acquire_timeout.is_zero() {
            return Err("获取连接超时时间必须大于0".to_string());
        }
        
        Ok(())
    }
}

/// 连接池配置构建器
pub struct ConnectionPoolConfigBuilder {
    config: ConnectionPoolConfig,
}

impl ConnectionPoolConfigBuilder {
    /// 创建新的构建器
    pub fn new() -> Self {
        Self {
            config: ConnectionPoolConfig::default(),
        }
    }

    /// 设置最大连接数
    pub fn max_connections(mut self, max_connections: u32) -> Self {
        self.config.max_connections = max_connections;
        self
    }

    /// 设置最小连接数
    pub fn min_connections(mut self, min_connections: u32) -> Self {
        self.config.min_connections = min_connections;
        self
    }

    /// 设置连接超时时间
    pub fn connection_timeout(mut self, timeout: Duration) -> Self {
        self.config.connection_timeout = timeout;
        self
    }

    /// 设置空闲超时时间
    pub fn idle_timeout(mut self, timeout: Duration) -> Self {
        self.config.idle_timeout = timeout;
        self
    }

    /// 设置获取连接超时时间
    pub fn acquire_timeout(mut self, timeout: Duration) -> Self {
        self.config.acquire_timeout = timeout;
        self
    }

    /// 设置连接验证间隔
    pub fn validation_interval(mut self, interval: Duration) -> Self {
        self.config.validation_interval = interval;
        self
    }

    /// 设置是否启用连接验证
    pub fn validation_enabled(mut self, enabled: bool) -> Self {
        self.config.validation_enabled = enabled;
        self
    }
}

impl ConfigBuilder<ConnectionPoolConfig> for ConnectionPoolConfigBuilder {
    fn build(self) -> Result<ConnectionPoolConfig, String> {
        self.config.validate()?;
        Ok(self.config)
    }

    fn validate(&self) -> Result<(), String> {
        self.config.validate()
    }
}

impl Default for ConnectionPoolConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// 重试配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RetryConfig {
    /// 最大重试次数
    pub max_attempts: u32,
    /// 基础延迟时间
    pub base_delay: Duration,
    /// 最大延迟时间
    pub max_delay: Duration,
    /// 重试条件
    pub retry_conditions: Vec<String>,
    /// 是否启用指数退避
    pub exponential_backoff: bool,
    /// 退避乘数
    pub backoff_multiplier: f64,
    /// 随机抖动
    pub jitter: bool,
}

impl Default for RetryConfig {
    fn default() -> Self {
        Self {
            max_attempts: 3,
            base_delay: Duration::from_millis(100),
            max_delay: Duration::from_secs(30),
            retry_conditions: vec![
                "NetworkError".to_string(),
                "Timeout".to_string(),
                "ServerError".to_string(),
            ],
            exponential_backoff: true,
            backoff_multiplier: 2.0,
            jitter: true,
        }
    }
}

impl RetryConfig {
    /// 创建配置构建器
    pub fn builder() -> RetryConfigBuilder {
        RetryConfigBuilder::new()
    }

    /// 验证配置的有效性
    pub fn validate(&self) -> Result<(), String> {
        if self.max_attempts == 0 {
            return Err("最大重试次数必须大于0".to_string());
        }
        
        if self.base_delay.is_zero() {
            return Err("基础延迟时间必须大于0".to_string());
        }
        
        if self.max_delay < self.base_delay {
            return Err("最大延迟时间不能小于基础延迟时间".to_string());
        }
        
        if self.backoff_multiplier <= 1.0 {
            return Err("退避乘数必须大于1.0".to_string());
        }
        
        Ok(())
    }

    /// 计算重试延迟时间
    pub fn calculate_delay(&self, attempt: u32) -> Duration {
        if !self.exponential_backoff {
            return self.base_delay;
        }
        
        let multiplier = self.backoff_multiplier.powi(attempt as i32);
        let delay = self.base_delay.mul_f64(multiplier);
        
        let delay = if delay > self.max_delay {
            self.max_delay
        } else {
            delay
        };
        
        if self.jitter {
            // 添加 ±25% 的随机抖动
            let jitter_range = delay.as_millis() as f64 * 0.25;
            let jitter = (rand::random::<f64>() - 0.5) * 2.0 * jitter_range;
            let jittered_millis = (delay.as_millis() as f64 + jitter).max(0.0) as u64;
            Duration::from_millis(jittered_millis)
        } else {
            delay
        }
    }
}

/// 重试配置构建器
pub struct RetryConfigBuilder {
    config: RetryConfig,
}

impl RetryConfigBuilder {
    /// 创建新的构建器
    pub fn new() -> Self {
        Self {
            config: RetryConfig::default(),
        }
    }

    /// 设置最大重试次数
    pub fn max_attempts(mut self, attempts: u32) -> Self {
        self.config.max_attempts = attempts;
        self
    }

    /// 设置基础延迟时间
    pub fn base_delay(mut self, delay: Duration) -> Self {
        self.config.base_delay = delay;
        self
    }

    /// 设置最大延迟时间
    pub fn max_delay(mut self, delay: Duration) -> Self {
        self.config.max_delay = delay;
        self
    }

    /// 添加重试条件
    pub fn add_retry_condition(mut self, condition: String) -> Self {
        self.config.retry_conditions.push(condition);
        self
    }

    /// 设置重试条件
    pub fn retry_conditions(mut self, conditions: Vec<String>) -> Self {
        self.config.retry_conditions = conditions;
        self
    }

    /// 设置是否启用指数退避
    pub fn exponential_backoff(mut self, enabled: bool) -> Self {
        self.config.exponential_backoff = enabled;
        self
    }

    /// 设置退避乘数
    pub fn backoff_multiplier(mut self, multiplier: f64) -> Self {
        self.config.backoff_multiplier = multiplier;
        self
    }

    /// 设置是否启用随机抖动
    pub fn jitter(mut self, enabled: bool) -> Self {
        self.config.jitter = enabled;
        self
    }
}

impl ConfigBuilder<RetryConfig> for RetryConfigBuilder {
    fn build(self) -> Result<RetryConfig, String> {
        self.config.validate()?;
        Ok(self.config)
    }

    fn validate(&self) -> Result<(), String> {
        self.config.validate()
    }
}

impl Default for RetryConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// 超时配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimeoutConfig {
    /// 连接超时时间
    pub connect_timeout: Duration,
    /// 请求超时时间
    pub request_timeout: Duration,
    /// 读取超时时间
    pub read_timeout: Duration,
    /// 写入超时时间
    pub write_timeout: Duration,
    /// 空闲超时时间
    pub idle_timeout: Duration,
}

impl Default for TimeoutConfig {
    fn default() -> Self {
        Self {
            connect_timeout: Duration::from_secs(10),
            request_timeout: Duration::from_secs(30),
            read_timeout: Duration::from_secs(30),
            write_timeout: Duration::from_secs(30),
            idle_timeout: Duration::from_secs(60),
        }
    }
}

impl TimeoutConfig {
    /// 创建配置构建器
    pub fn builder() -> TimeoutConfigBuilder {
        TimeoutConfigBuilder::new()
    }

    /// 验证配置的有效性
    pub fn validate(&self) -> Result<(), String> {
        if self.connect_timeout.is_zero() {
            return Err("连接超时时间必须大于0".to_string());
        }
        
        if self.request_timeout.is_zero() {
            return Err("请求超时时间必须大于0".to_string());
        }
        
        if self.read_timeout.is_zero() {
            return Err("读取超时时间必须大于0".to_string());
        }
        
        if self.write_timeout.is_zero() {
            return Err("写入超时时间必须大于0".to_string());
        }
        
        Ok(())
    }
}

/// 超时配置构建器
pub struct TimeoutConfigBuilder {
    config: TimeoutConfig,
}

impl TimeoutConfigBuilder {
    /// 创建新的构建器
    pub fn new() -> Self {
        Self {
            config: TimeoutConfig::default(),
        }
    }

    /// 设置连接超时时间
    pub fn connect_timeout(mut self, timeout: Duration) -> Self {
        self.config.connect_timeout = timeout;
        self
    }

    /// 设置请求超时时间
    pub fn request_timeout(mut self, timeout: Duration) -> Self {
        self.config.request_timeout = timeout;
        self
    }

    /// 设置读取超时时间
    pub fn read_timeout(mut self, timeout: Duration) -> Self {
        self.config.read_timeout = timeout;
        self
    }

    /// 设置写入超时时间
    pub fn write_timeout(mut self, timeout: Duration) -> Self {
        self.config.write_timeout = timeout;
        self
    }

    /// 设置空闲超时时间
    pub fn idle_timeout(mut self, timeout: Duration) -> Self {
        self.config.idle_timeout = timeout;
        self
    }
}

impl ConfigBuilder<TimeoutConfig> for TimeoutConfigBuilder {
    fn build(self) -> Result<TimeoutConfig, String> {
        self.config.validate()?;
        Ok(self.config)
    }

    fn validate(&self) -> Result<(), String> {
        self.config.validate()
    }
}

impl Default for TimeoutConfigBuilder {
    fn default() -> Self {
        Self::new()
    }
}

/// 配置工厂工具
pub struct ConfigFactory;

impl ConfigFactory {
    /// 创建用于开发环境的连接池配置
    pub fn create_dev_connection_pool() -> ConnectionPoolConfig {
        ConnectionPoolConfig::builder()
            .max_connections(20)
            .min_connections(5)
            .connection_timeout(Duration::from_secs(5))
            .build()
            .unwrap()
    }

    /// 创建用于生产环境的连接池配置
    pub fn create_prod_connection_pool() -> ConnectionPoolConfig {
        ConnectionPoolConfig::builder()
            .max_connections(100)
            .min_connections(20)
            .connection_timeout(Duration::from_secs(30))
            .validation_enabled(true)
            .build()
            .unwrap()
    }

    /// 创建快速重试配置
    pub fn create_fast_retry() -> RetryConfig {
        RetryConfig::builder()
            .max_attempts(3)
            .base_delay(Duration::from_millis(100))
            .max_delay(Duration::from_secs(1))
            .exponential_backoff(true)
            .build()
            .unwrap()
    }

    /// 创建慢速重试配置
    pub fn create_slow_retry() -> RetryConfig {
        RetryConfig::builder()
            .max_attempts(5)
            .base_delay(Duration::from_secs(1))
            .max_delay(Duration::from_secs(30))
            .exponential_backoff(true)
            .jitter(true)
            .build()
            .unwrap()
    }

    /// 创建严格的超时配置
    pub fn create_strict_timeout() -> TimeoutConfig {
        TimeoutConfig::builder()
            .connect_timeout(Duration::from_secs(3))
            .request_timeout(Duration::from_secs(10))
            .read_timeout(Duration::from_secs(10))
            .write_timeout(Duration::from_secs(10))
            .build()
            .unwrap()
    }

    /// 创建宽松的超时配置
    pub fn create_relaxed_timeout() -> TimeoutConfig {
        TimeoutConfig::builder()
            .connect_timeout(Duration::from_secs(10))
            .request_timeout(Duration::from_secs(60))
            .read_timeout(Duration::from_secs(60))
            .write_timeout(Duration::from_secs(60))
            .idle_timeout(Duration::from_secs(300))
            .build()
            .unwrap()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_connection_pool_config_builder() {
        let config = ConnectionPoolConfig::builder()
            .max_connections(50)
            .min_connections(10)
            .connection_timeout(Duration::from_secs(15))
            .build()
            .unwrap();

        assert_eq!(config.max_connections, 50);
        assert_eq!(config.min_connections, 10);
        assert_eq!(config.connection_timeout, Duration::from_secs(15));
    }

    #[test]
    fn test_retry_config_builder() {
        let config = RetryConfig::builder()
            .max_attempts(5)
            .base_delay(Duration::from_millis(200))
            .exponential_backoff(true)
            .build()
            .unwrap();

        assert_eq!(config.max_attempts, 5);
        assert_eq!(config.base_delay, Duration::from_millis(200));
        assert!(config.exponential_backoff);
    }

    #[test]
    fn test_timeout_config_builder() {
        let config = TimeoutConfig::builder()
            .connect_timeout(Duration::from_secs(5))
            .request_timeout(Duration::from_secs(20))
            .build()
            .unwrap();

        assert_eq!(config.connect_timeout, Duration::from_secs(5));
        assert_eq!(config.request_timeout, Duration::from_secs(20));
    }

    #[test]
    fn test_config_factory() {
        let dev_pool = ConfigFactory::create_dev_connection_pool();
        assert_eq!(dev_pool.max_connections, 20);

        let prod_pool = ConfigFactory::create_prod_connection_pool();
        assert_eq!(prod_pool.max_connections, 100);

        let fast_retry = ConfigFactory::create_fast_retry();
        assert_eq!(fast_retry.max_attempts, 3);

        let slow_retry = ConfigFactory::create_slow_retry();
        assert_eq!(slow_retry.max_attempts, 5);
    }

    #[test]
    fn test_retry_delay_calculation() {
        let config = RetryConfig::builder()
            .base_delay(Duration::from_millis(100))
            .backoff_multiplier(2.0)
            .max_delay(Duration::from_secs(10))
            .jitter(false)
            .build()
            .unwrap();

        let delay1 = config.calculate_delay(0);
        let delay2 = config.calculate_delay(1);
        let delay3 = config.calculate_delay(2);

        assert_eq!(delay1, Duration::from_millis(100));
        assert_eq!(delay2, Duration::from_millis(200));
        assert_eq!(delay3, Duration::from_millis(400));
    }
}